#include "ns2009.h"

#include "pico/stdlib.h"
#include "hardware/i2c.h"
#include "hardware/gpio.h"

/* Macro Definition
********************************************************************************************************/
#define NS2009_I2C_SDA_PIN 20
#define NS2009_I2C_SCL_PIN 21
#define NS2009_I2C_PORT    i2c0
#define NS2009_I2C_BAUD    (100 * 1000)
#define NS2009_IRQ_PIN     22


/* Function Declaration
********************************************************************************************************/
static void gpio_callback(uint gpio, uint32_t events);


/* Structure Definition
********************************************************************************************************/



/* Global Variables
********************************************************************************************************/



/* Public Functions
********************************************************************************************************/
/*
**********************************************************************
* @fun     :bsp_ns2009_init
* @brief   :
* @param   :
* @return  :None
* @remark  :
**********************************************************************
*/
uint8_t ns2009_init(void)
{
    i2c_init(NS2009_I2C_PORT, NS2009_I2C_BAUD);
    gpio_set_function(NS2009_I2C_SDA_PIN, GPIO_FUNC_I2C);
    gpio_set_function(NS2009_I2C_SCL_PIN, GPIO_FUNC_I2C);
    gpio_pull_up(NS2009_I2C_SDA_PIN);
    gpio_pull_up(NS2009_I2C_SCL_PIN);

    // IRQ
    // gpio_set_irq_enabled_with_callback(NS2009_IRQ_PIN, GPIO_IRQ_EDGE_FALL, true, &gpio_callback);

    return 0;
}

/*
**********************************************************************
* @fun     :ns2009_read
* @brief   :读取ns2009数据
* @param   :
* @return  :None
* @remark  :
**********************************************************************
*/
uint32_t ns2009_read(const uint8_t _cmd)
{
    uint8_t tp_adc[2] = {0};

    i2c_write_blocking(NS2009_I2C_PORT, NS2009_ADDR, &_cmd, 1, true);
    i2c_read_blocking(NS2009_I2C_PORT, NS2009_ADDR, (uint8_t*)&tp_adc, 2, false);

    return (tp_adc[0] << 8 | tp_adc[1]) >> 4;
}

/*
**********************************************************************
* @fun     :ns2009_getPress
* @brief   :读取ns2009压力数据
* @param   :
* @return  :None
* @remark  :
**********************************************************************
*/
uint32_t ns2009_getPress(void)
{
    return ns2009_read(NS2009_LOW_POWER_READ_Z1);
}

/*
**********************************************************************
* @fun     :ns2009_getPos
* @brief   :获取ns2009坐标数据
* @param   :
* @return  :None
* @remark  :
**********************************************************************
*/
uint32_t ns2009_getPos(uint32_t* _pos)
{
    uint32_t x = 0, y = 0, z = 0;

    z = ns2009_getPress();

    if((z > 70) && (z < 2000))
    {
        x = ns2009_read(NS2009_LOW_POWER_READ_X);
        y = ns2009_read(NS2009_LOW_POWER_READ_Y);

        *(_pos + 0) = x * SCREEN_X_PIXEL / 4096;    // 4096 = 2 ^ 12
        *(_pos + 1) = y * SCREEN_Y_PIXEL / 4096;
    }
    else
    {
        *(_pos + 0) = 0;
        *(_pos + 1) = 0;
    }

    return z;
}


bool ns2009_is_pressed(void)
{
    uint32_t z = ns2009_getPress();

    if((z > 70) && (z < 2000))
    {
        return true;
    }

    return false;
}

static uint32_t last_adc_x, last_adc_y;

void ns2009_get_xy(uint16_t* x, uint16_t* y)
{
    uint32_t x_adc = ns2009_read(NS2009_LOW_POWER_READ_X);
    uint32_t y_adc = ns2009_read(NS2009_LOW_POWER_READ_Y);

    last_adc_x = x_adc;
    last_adc_y = y_adc;

    *x = x_adc * SCREEN_X_PIXEL / 4096;    // 4096 = 2 ^ 12
    *y = SCREEN_Y_PIXEL - (y_adc * SCREEN_Y_PIXEL / 4096);
}


void ns2009_read_adc(uint32_t* x_adc, uint32_t* y_adc)
{
    *x_adc = last_adc_x;
    *y_adc = last_adc_y;

    // *x_adc = ns2009_read(NS2009_LOW_POWER_READ_X);
    // *y_adc = ns2009_read(NS2009_LOW_POWER_READ_Y);
}

#if 0
#include "my_log.h"
void ns2009_test(void)
{
    uint32_t data[2];
    uint32_t z = 0;

    ns2009_init();

    // for(uint16_t i = 0; i < 1000; i++)
    // {
    //     sleep_ms(500);
    //     z = ns2009_getPos(data);

    //     log_i("z,x,y:%d,(%d,%d)", z, data[0], data[1]);
    // }
}

static void gpio_callback(uint gpio, uint32_t events)
{
    uint32_t data[2];
    uint32_t z = 0;

    // Put the GPIO event(s) that just happened into event_str
    // so we can print it

    if(gpio == NS2009_IRQ_PIN)
    {
        z = ns2009_getPos(data);

        log_i("z,x,y:%d,(%d,%d)", z, data[0], data[1]);
    }
}
#endif

/* Private Functions
********************************************************************************************************/



/* End Of File
********************************************************************************************************/
